﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.IO;
using RA.Common;
using System.Reflection;
using System.Text.RegularExpressions;
using RA.TextServices;

namespace RA.CompileServices
{
    public class CompileService
    {
        public void CompileTextFinderAgent(string uriTemplate, string xPath, IEnumerable<string> keys, string fileName)
        {
            var folder = AppDomain.CurrentDomain.BaseDirectory + "GrabberAgentTemplates\\";
            string template = File.ReadAllText(folder + "GrabberAgentTemplate.txt");

            var text = template.Replace("%urlTemplate%", uriTemplate)
                                .Replace("%bodyTemplate%", xPath)
                                .Replace("%listKeys%",'"'+ String.Join("\",\"", keys) +'"');

            CompileAgent(text, AppDomain.CurrentDomain.BaseDirectory + "TextAgents\\" + fileName);
        }

        public IGrabberAgent GetGrabberAgent(string agentName)
        {
            Assembly assembly = Assembly.LoadFrom(agentName);
            Type type = assembly.GetTypes()[0];
            return (IGrabberAgent)Activator.CreateInstance(type);
        }

        public void CompileImageRecognitionAgent(Settings settings, string fileName)
        {
            var agentText = PastStringSettings(settings);
            CompileAgent(agentText, AppDomain.CurrentDomain.BaseDirectory + "Multiagent\\" + fileName);
        }
        public void ComplierInteraction(string fileName)
        {
            var folder = AppDomain.CurrentDomain.BaseDirectory + "AgentTemplates\\";
            var template = File.ReadAllText(folder + "interactions.txt");
            CompileAgent(template, AppDomain.CurrentDomain.BaseDirectory + "Multiagent\\" + fileName);
        }
        public void CompileAgent(string csText, string fileName)
        {
            var text = csText;//File.ReadAllText(@"D:\Box\univer\two\RecognitionAgent\RA.Services\ImageProcessor.cs");
            var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
            var parameters = new CompilerParameters(new[] {
                "Microsoft.CSharp.dll",
                "Libs\\SgmlReaderDll.dll",
                "RA.TextServices.dll", 
                "mscorlib.dll",
                "Emgu.CV.dll", 
                "Emgu.Util.dll", 
                "System.Core.dll",
                "System.dll",
                "System.Xml.dll", 
                "System.Drawing.dll",
                @"RA.Common.dll",
                @"ClassLibrary.dll"}, fileName + ".dll", true);
            parameters.GenerateExecutable = false;

            CompilerResults results = csc.CompileAssemblyFromSource(parameters, text);
        }

        public IAgent GetAgent(string agentName)
        {
            Assembly assembly = Assembly.LoadFrom(agentName);
            Type type =  assembly.GetTypes()[0];//assembly.GetType("ImageProcessor");
            return (IAgent)Activator.CreateInstance(type);
        }

        string PastIteraction(Settings settings)
        {
            var folder = AppDomain.CurrentDomain.BaseDirectory + "AgentTemplates\\";
            string template = File.ReadAllText(folder + "agentTemplateProccess.txt");
            Dictionary<string, string> changes = new Dictionary<string, string>();
            foreach (Match match in Regex.Matches(template, @"%(?<FieldName>\w*)%"))
            {
                var replacement = match.Value;
                var fieldName = match.Groups["FieldName"].Value;

                var fieldValue = FollowPropertyPath(settings, fieldName);
                string fieldValueStr = fieldValue.ToString().Replace(",", ".");
                if (fieldValue is Boolean)
                    fieldValueStr = fieldValueStr.ToLower();

                changes.Add(replacement, fieldValueStr);
            }

            template = Replace(template, changes);

            var templateMethodFile = settings.Method.ToString() + ".txt";

            return template.Replace("@MethodImpl@", File.ReadAllText(folder + templateMethodFile));
        }
        #region Utils
        string PastStringSettings(Settings settings)
        {
            var folder = AppDomain.CurrentDomain.BaseDirectory + "AgentTemplates\\";
            string template = File.ReadAllText(folder + "agentTemplateProccess.txt");
            Dictionary<string, string> changes = new Dictionary<string, string>();
            foreach (Match match in Regex.Matches(template, @"%(?<FieldName>\w*)%"))
            {
                var replacement = match.Value;
                var fieldName = match.Groups["FieldName"].Value;

                var fieldValue = FollowPropertyPath(settings, fieldName);
                string fieldValueStr = fieldValue.ToString().Replace(",",".");
                if (fieldValue is Boolean)
                    fieldValueStr = fieldValueStr.ToLower();

                changes.Add(replacement, fieldValueStr);
            }

            template = Replace(template, changes);

            var templateMethodFile = settings.Method.ToString() + ".txt";

            return template.Replace("@MethodImpl@", File.ReadAllText(folder + templateMethodFile));
        }


        object FollowPropertyPath(object value, string path)
        {
            Type currentType = value.GetType();

            foreach (string propertyName in path.Split('.'))
            {
                PropertyInfo property = currentType.GetProperty(propertyName);
                value = property.GetValue(value, null);
                currentType = property.PropertyType;
            }
            return value;
        }

        string Replace(string template, Dictionary<string, string> changes)
        {
            foreach (var change in changes)
                template = template.Replace(change.Key, change.Value);

            return template;
        }
        #endregion Utils
    }
}
